/*
* This file is part of QSerialDevice, an open-source cross-platform library
* Copyright (C) 2009  Denis Shienkov
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
* Contact Denis Shienkov:
*          e-mail: <scapig2@yandex.ru>
*             ICQ: 321789831
*/

#include <QtCore/QSocketNotifier>
#include <sys/ioctl.h>

#include "serialnotifier.h"
#include "serialnotifier_p.h"

//#define SERIALNOTIFIER_UNIX_DEBUG

#ifdef SERIALNOTIFIER_UNIX_DEBUG
#include <QtCore/QDebug>
#endif


SerialNotifierPrivate::SerialNotifierPrivate()
        : m_enabled(false), m_eventNotifier(0)
{
}

SerialNotifierPrivate::~SerialNotifierPrivate()
{
    this->setEnabled(false);
}

void SerialNotifierPrivate::init(Qt::HANDLE descriptor, SerialNotifier::Type type)
{
    Q_Q(SerialNotifier);

    this->m_descriptor = descriptor;
    this->m_type = type;

    QSocketNotifier::Type sntype;
    switch (this->m_type) {
    case SerialNotifier::Read:
        sntype = QSocketNotifier::Read; break;
    case SerialNotifier::Write:
        sntype = QSocketNotifier::Write; break;
    case SerialNotifier::Exception:
        sntype = QSocketNotifier::Exception; break;
    default: return;
    }

    this->m_eventNotifier = new QSocketNotifier((int)((long)this->m_descriptor), sntype, q);
    QObject::connect(this->m_eventNotifier, SIGNAL(activated(int)), q, SLOT(_q_updateNotifier()));
}

void SerialNotifierPrivate::setEnabled(bool enable)
{
    if (!this->isValid())
        return;
    this->m_eventNotifier->setEnabled(enable);
    this->m_enabled = enable;
}

void SerialNotifierPrivate::_q_updateNotifier()
{
    Q_Q(SerialNotifier);

    if (!this->isValid())
        return;

    bool result = false;

    switch (this->m_type) {
    case SerialNotifier::Read: {
            size_t nbytes = 0;
            //TODO: whether there has been done to build a multi-platform *.nix. (FIONREAD) ?
#if defined (FIONREAD)
            if ( -1 == ::ioctl((int)((long)this->m_descriptor), FIONREAD, &nbytes) )
#else
            if ( -1 == ::ioctl((int)((long)this->m_descriptor), TIOCINQ, &nbytes) )
#endif
            {
                return;
            }

            if (nbytes)
                result = true;
        }
        break;
    default:
        result = true;
    }

    if (result)
        emit q->activated();
}

bool SerialNotifierPrivate::isValid() const
{
    return ( (-1 != (int)((long)this->m_descriptor))
            && (0 != this->m_eventNotifier) );
}

#include "moc_serialnotifier.cpp"



